/*
*	Project: Aethon
*
*	File: Director.cpp
*
*	Author: Caleb Reinking
*
*	Date: 2/27/2009
*
*   Purpose: The director is the actual run class that includes int main() and
*            communicates directly with the Scene and StageHand classes
*/

#include "../include/Director.h"
#include <GL/gl.h>
#include <GL/glut.h>
#include "../include/Control.h"
#include "../include/Eye.h"
#include "../include/vector3f.h"
#include "../include/Model.h"
#include "../include/ModelPart.h"
#include "../include/Eye.h"
#include "../include/Terrain.h"
#include <iostream>
#include <assert.h>
#include <string>

using namespace std;
	
// Constants
const unsigned int MAX_BUFFER_SIZE = 40;
const int WINDOW_WIDTH = 1024;
const int WINDOW_HEIGHT = 786;
const int DISTANCE = 20;	

// Global Variables
int sizeOfTeapot = 6;
bool wireFrameDesired = false;
Model myModel;
Model camera;
Eye myeye;
Control myControl;
Terrain testTerrain;
//int xRotateAmt = 0;
//int yRotateAmt = 0;
//int zRotateAmt = 0;
bool axisLinesDesired = true;

// Function Prototypes
void display(void);
void myReshape(int w, int h);
void createModel();
void update();//test director code, updates model velocity and direction, 
//will also call collision check for physmanager
void generateNewPosition(Model& modelA);//test for velocity based movement

// Caleb's Function Protos
//void handleKeyboard( unsigned char key, int x, int y );
void drawAxisLines();
//void handleMotion( int x, int y );
//void mouseButton(int button, int state, int x, int y);

//-------------------------------------------------------------------------	
//------------------- Methods ---------------------------------------------
//##########################################################################
void Director::run()
{
   
}
	
//##########################################################################
int main( int argc, char* argv[] )
{
        
    //srand(time(0));
    testTerrain = Terrain();
	testTerrain.load( "heightmapTexture", "texture2flip" );
    //cout << "terrain created" << endl;
	
    glutInit(&argc, argv);
    
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT);
    glutCreateWindow("3D Teapot (Orthographic)");
    glutReshapeFunc(myReshape);
    glutDisplayFunc(display);
    glutSetCursor(GLUT_CURSOR_NONE);
    glutKeyboardFunc(Control::keyboardHandle);
    glutPassiveMotionFunc(Control::mouseHandle);
    createModel();//create test model for control to adjust
    glutWarpPointer(320,240);//set pointer at center
    myControl.setModelPtr(&camera);//set control pointer as camera
    
    
    glEnable(GL_DEPTH_TEST);
    glClearDepth(1.0);
    glEnable(GL_TEXTURE_2D); 
    glClearColor(0.5, 0.5, 0.5, 1.0); // Gray
    
    glutMainLoop();
    return 0;
        
}

// ######################################################################
void display(void)
{
glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

if (wireFrameDesired)
   glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
else
   glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

update();

//cout<<"directionx: "<<camera.getDirection().v[0]<< endl;
//cout<<"directiony: "<<camera.getDirection().v[1]<< endl;
//cout<<"directionz: "<<camera.getDirection().v[2]<< endl;
//cout<<"velocityX: "<<camera.getVelocity().v[0]<< endl;
//cout<<"velocityY: "<<camera.getVelocity().v[1]<< endl;
//cout<<"velocityZ: "<<camera.getVelocity().v[2]<< endl;
//cout<<"PositionX: "<<camera.getPosition().v[0]<< endl;
//cout<<"PositionY: "<<camera.getPosition().v[1]<< endl;
//cout<<"PositionZ: "<<camera.getPosition().v[2]<< endl;

testTerrain.display();
drawAxisLines();

//markers used for rotation testing
/*glPushMatrix();
glColor3f(1,1,1);//white
glTranslatef(0,0,80);//+z marker
glutSolidTeapot(6.0);
glPopMatrix();

glPushMatrix();
glColor3f(1,0,0);
glTranslatef(80,0,0);//red +x marker
glutSolidTeapot(6.0);
glPopMatrix();

glPushMatrix();
glColor3f(0,1,0);//green
glTranslatef(0,0,-80);//-z marker
glutSolidTeapot(6.0);
glPopMatrix();

glPushMatrix();
glColor3f(0,0,1);
glTranslatef(-80,0,0);//blue -x marker
glutSolidTeapot(6.0);
glPopMatrix();*/

glFlush();
glutSwapBuffers();
} // End display

void myReshape(int width, int height)
{
const int DISTANCE = 10000;
const int FOV_ANGLE = 45;

glViewport(0, 0, width, height);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();

gluPerspective(FOV_ANGLE,  (float) width / (float) height, 1.0, DISTANCE);

cout << "New window size: " << width << " x " << height << endl;
glMatrixMode(GL_MODELVIEW);
} // End myReshape

void createModel()
{
	vector3f pos(0,8.0,0);
	vector3f dir(0,0,0);
	vector3f vel(0,0,0);
	camera.setPosition(pos);
	camera.setDirection(dir);
	camera.setVelocity(vel);
	
	vector3f look(0,0,1);
	myeye.setLookAt(look);//set look to zeros
	myeye.setIsActive(true);
	myeye.update(pos,dir);
	
}//end function

void update()
{
myControl.updateVelocity();
myControl.updateDirection();
myeye.update(camera.getPosition(),camera.getDirection());
generateNewPosition(camera);
}

void generateNewPosition(Model& modelA)
{//for now it just sets position, ignoring collisions so that we can move the camera
	vector3f tempVel = modelA.getVelocity();
	vector3f tempPos = modelA.getPosition();

	tempPos.v[0] += tempVel.v[0];
	tempPos.v[1] += tempVel.v[1];
	tempPos.v[2] += tempVel.v[2];
	
	modelA.setPosition(tempPos);
	vector3f zeroVect(0,0,0);
	modelA.setVelocity(zeroVect);
}//end gennewPosition
	
//####################################
void drawAxisLines()
{
     glBegin( GL_LINES );
        glLineWidth(3);
        glColor3ub( 255, 0, 0 );
        glVertex3f( 0.0, 0.0, 0.0 );
        glVertex3f( 100.0, 0.0, 0.0 );
        
        glColor3ub( 0, 255, 0 );
        glVertex3f( 0.0, 0.0, 0.0 );
        glVertex3f( 0.0, 100.0, 0.0 );
        
        glColor3ub( 0, 0, 255 );
        glVertex3f( 0.0, 0.0, 0.0 );
        glVertex3f( 0.0, 0.0, 100.0 );
        
        glLineWidth(1);
     glEnd();
}
